DUMP_FRAMEBUFFER = 1 << 3
} OffscreenFlags;
+typedef struct
+{
+ int texture_id;
+ float x;
+ float y;
+ float x2;
+ float y2;
+} TextureRegion;
+
+static inline void
+init_full_texture_region (TextureRegion *r,
+ int texture_id)
+{
+ r->texture_id = texture_id;
+ r->x = 0;
+ r->y = 0;
+ r->x2 = 1;
+ r->y2 = 1;
+}
+
static void G_GNUC_UNUSED
print_render_node_tree (GskRenderNode *root, int level)
{
return has_color;
}
-static void
-get_gl_scaling_filters (GskRenderNode *node,
- int *min_filter_r,
- int *mag_filter_r)
-{
- *min_filter_r = GL_LINEAR;
- *mag_filter_r = GL_LINEAR;
-}
-
static inline void
rgba_to_float (const GdkRGBA *c,
float *f)
RenderOpBuilder *builder,
const graphene_rect_t *bounds,
GskRenderNode *child_node,
- int *texture_id,
+ TextureRegion *region_out,
gboolean *is_offscreen,
guint flags);
static void gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
ops_draw (builder, vertex_data);
}
+static inline void
+upload_texture (GskGLRenderer *self,
+ GdkTexture *texture,
+ TextureRegion *out_region)
+{
+ int texture_id;
+
+ if (texture->width <= 128 &&
+ texture->height <= 128)
+ {
+ graphene_rect_t trect;
+
+ gsk_gl_icon_cache_lookup_or_add (self->icon_cache,
+ texture,
+ &texture_id,
+ &trect);
+ out_region->x = trect.origin.x;
+ out_region->y = trect.origin.y;
+ out_region->x2 = out_region->x + trect.size.width;
+ out_region->y2 = out_region->y + trect.size.height;
+ }
+ else
+ {
+ texture_id = gsk_gl_driver_get_texture_for_texture (self->gl_driver,
+ texture,
+ GL_LINEAR,
+ GL_LINEAR);
+ out_region->x = 0;
+ out_region->y = 0;
+ out_region->x2 = 1;
+ out_region->y2 = 1;
+ }
+
+ out_region->texture_id = texture_id;
+}
+
static inline void
render_texture_node (GskGLRenderer *self,
GskRenderNode *node,
}
else
{
- int texture_id;
- float tx = 0, ty = 0, tx2 = 1, ty2 = 1;
-
- if (texture->width <= 128 &&
- texture->height <= 128)
- {
- graphene_rect_t trect;
-
- gsk_gl_icon_cache_lookup_or_add (self->icon_cache,
- texture,
- &texture_id,
- &trect);
- tx = trect.origin.x;
- ty = trect.origin.y;
- tx2 = tx + trect.size.width;
- ty2 = ty + trect.size.height;
- }
- else
- {
- int gl_min_filter = GL_NEAREST, gl_mag_filter = GL_NEAREST;
- get_gl_scaling_filters (node, &gl_min_filter, &gl_mag_filter);
+ TextureRegion r;
- texture_id = gsk_gl_driver_get_texture_for_texture (self->gl_driver,
- texture,
- gl_min_filter,
- gl_mag_filter);
- }
+ upload_texture (self, texture, &r);
ops_set_program (builder, &self->blit_program);
- ops_set_texture (builder, texture_id);
+ ops_set_texture (builder, r.texture_id);
ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
- { { min_x, min_y }, { tx, ty }, },
- { { min_x, max_y }, { tx, ty2 }, },
- { { max_x, min_y }, { tx2, ty }, },
+ { { min_x, min_y }, { r.x, r.y }, },
+ { { min_x, max_y }, { r.x, r.y2 }, },
+ { { max_x, min_y }, { r.x2, r.y }, },
- { { max_x, max_y }, { tx2, ty2 }, },
- { { min_x, max_y }, { tx, ty2 }, },
- { { max_x, min_y }, { tx2, ty }, },
+ { { max_x, max_y }, { r.x2, r.y2 }, },
+ { { min_x, max_y }, { r.x, r.y2 }, },
+ { { max_x, min_y }, { r.x2, r.y }, },
});
}
}
const float min_y = child->bounds.origin.y;
const float max_x = min_x + child->bounds.size.width;
const float max_y = min_y + child->bounds.size.height;
- int texture_id;
+ TextureRegion region;
gboolean is_offscreen;
/* For non-trivial transforms, we draw everything on a texture and then
* draw the texture transformed. */
add_offscreen_ops (self, builder,
&child->bounds,
child,
- &texture_id, &is_offscreen,
+ ®ion, &is_offscreen,
RESET_CLIP | RESET_OPACITY);
gsk_transform_to_matrix (node_transform, &mat);
ops_push_modelview (builder, node_transform);
- ops_set_texture (builder, texture_id);
+ ops_set_texture (builder, region.texture_id);
ops_set_program (builder, &self->blit_program);
if (is_offscreen)
{
const GskQuadVertex offscreen_vertex_data[GL_N_VERTICES] = {
- { { min_x, min_y }, { 0, 1 }, },
- { { min_x, max_y }, { 0, 0 }, },
- { { max_x, min_y }, { 1, 1 }, },
+ { { min_x, min_y }, { region.x, region.y2 }, },
+ { { min_x, max_y }, { region.x, region.y }, },
+ { { max_x, min_y }, { region.x2, region.y2 }, },
- { { max_x, max_y }, { 1, 0 }, },
- { { min_x, max_y }, { 0, 0 }, },
- { { max_x, min_y }, { 1, 1 }, },
+ { { max_x, max_y }, { region.x2, region.y }, },
+ { { min_x, max_y }, { region.x, region.y }, },
+ { { max_x, min_y }, { region.x2, region.y2 }, },
};
ops_draw (builder, offscreen_vertex_data);
else
{
const GskQuadVertex onscreen_vertex_data[GL_N_VERTICES] = {
- { { min_x, min_y }, { 0, 0 }, },
- { { min_x, max_y }, { 0, 1 }, },
- { { max_x, min_y }, { 1, 0 }, },
+ { { min_x, min_y }, { region.x, region.y }, },
+ { { min_x, max_y }, { region.x, region.y2 }, },
+ { { max_x, min_y }, { region.x2, region.y }, },
- { { max_x, max_y }, { 1, 1 }, },
- { { min_x, max_y }, { 0, 1 }, },
- { { max_x, min_y }, { 1, 0 }, },
+ { { max_x, max_y }, { region.x2, region.y2 }, },
+ { { min_x, max_y }, { region.x, region.y2 }, },
+ { { max_x, min_y }, { region.x2, region.y }, },
};
ops_draw (builder, onscreen_vertex_data);
const float max_y = min_y + node->bounds.size.height;
graphene_matrix_t scale_matrix;
gboolean is_offscreen;
- int texture_id;
+ TextureRegion region;
/* NOTE: We are *not* transforming the clip by the current modelview here.
* We instead draw the untransformed clip to a texture and then transform
* that texture.
ops_push_clip (builder, &child_clip);
add_offscreen_ops (self, builder, &node->bounds,
child,
- &texture_id, &is_offscreen,
+ ®ion, &is_offscreen,
FORCE_OFFSCREEN | RESET_OPACITY);
ops_pop_clip (builder);
ops_set_program (builder, &self->blit_program);
- ops_set_texture (builder, texture_id);
+ ops_set_texture (builder, region.texture_id);
ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
{ { min_x, min_y }, { 0, 1 }, },
{ { min_x, max_y }, { 0, 0 }, },
{ { max_x, min_y }, { 1, 1 }, },
-
+
{ { max_x, max_y }, { 1, 0 }, },
{ { min_x, max_y }, { 0, 0 }, },
{ { max_x, min_y }, { 1, 1 }, },
const float max_x = min_x + node->bounds.size.width;
const float max_y = min_y + node->bounds.size.height;
GskRenderNode *child = gsk_color_matrix_node_get_child (node);
- int texture_id;
+ TextureRegion region;
gboolean is_offscreen;
add_offscreen_ops (self, builder,
&node->bounds,
child,
- &texture_id, &is_offscreen,
+ ®ion, &is_offscreen,
RESET_CLIP | RESET_OPACITY);
ops_set_program (builder, &self->color_matrix_program);
gsk_color_matrix_node_peek_color_matrix (node),
gsk_color_matrix_node_peek_color_offset (node));
- ops_set_texture (builder, texture_id);
+ ops_set_texture (builder, region.texture_id);
if (is_offscreen)
{
GskQuadVertex offscreen_vertex_data[GL_N_VERTICES] = {
- { { min_x, min_y }, { 0, 1 }, },
- { { min_x, max_y }, { 0, 0 }, },
- { { max_x, min_y }, { 1, 1 }, },
+ { { min_x, min_y }, { region.x, region.y2 }, },
+ { { min_x, max_y }, { region.x, region.y }, },
+ { { max_x, min_y }, { region.x2, region.y2 }, },
- { { max_x, max_y }, { 1, 0 }, },
- { { min_x, max_y }, { 0, 0 }, },
- { { max_x, min_y }, { 1, 1 }, },
+ { { max_x, max_y }, { region.x2, region.y }, },
+ { { min_x, max_y }, { region.x, region.y }, },
+ { { max_x, min_y }, { region.x2, region.y2 }, },
};
ops_draw (builder, offscreen_vertex_data);
}
else
{
- ops_draw (builder, vertex_data);
+ const GskQuadVertex onscreen_vertex_data[GL_N_VERTICES] = {
+ { { min_x, min_y }, { region.x, region.y }, },
+ { { min_x, max_y }, { region.x, region.y2 }, },
+ { { max_x, min_y }, { region.x2, region.y }, },
+
+ { { max_x, max_y }, { region.x2, region.y2 }, },
+ { { min_x, max_y }, { region.x, region.y2 }, },
+ { { max_x, min_y }, { region.x2, region.y }, },
+ };
+
+ ops_draw (builder, onscreen_vertex_data);
}
}
const float max_x = min_x + node->bounds.size.width;
const float max_y = min_y + node->bounds.size.height;
const float blur_radius = gsk_blur_node_get_radius (node);
- int texture_id;
+ TextureRegion region;
gboolean is_offscreen;
RenderOp op;
add_offscreen_ops (self, builder,
&node->bounds,
gsk_blur_node_get_child (node),
- &texture_id, &is_offscreen,
+ ®ion, &is_offscreen,
RESET_CLIP | FORCE_OFFSCREEN | RESET_OPACITY);
ops_set_program (builder, &self->blur_program);
op.blur.radius = gsk_blur_node_get_radius (node);
ops_add (builder, &op);
- ops_set_texture (builder, texture_id);
+ ops_set_texture (builder, region.texture_id);
if (is_offscreen)
{
{ { min_x, min_y }, { 0, 1 }, },
{ { min_x, max_y }, { 0, 0 }, },
{ { max_x, min_y }, { 1, 1 }, },
-
+
{ { max_x, max_y }, { 1, 0 }, },
{ { min_x, max_y }, { 0, 0 }, },
{ { max_x, min_y }, { 1, 1 }, },
const GskShadow *shadow = gsk_shadow_node_peek_shadow (node, i);
const float dx = shadow->dx;
const float dy = shadow->dy;
- int texture_id;
+ TextureRegion region;
gboolean is_offscreen;
g_assert (shadow->radius <= 0);
/* Draw the child offscreen, without the offset. */
add_offscreen_ops (self, builder,
&shadow_child->bounds,
- shadow_child, &texture_id, &is_offscreen,
+ shadow_child, ®ion, &is_offscreen,
RESET_CLIP | RESET_OPACITY);
ops_set_program (builder, &self->coloring_program);
ops_set_color (builder, &shadow->color);
- ops_set_texture (builder, texture_id);
+ ops_set_texture (builder, region.texture_id);
if (is_offscreen)
{
const GskQuadVertex offscreen_vertex_data[GL_N_VERTICES] = {
- { { dx + min_x, dy + min_y }, { 0, 1 }, },
- { { dx + min_x, dy + max_y }, { 0, 0 }, },
- { { dx + max_x, dy + min_y }, { 1, 1 }, },
+ { { dx + min_x, dy + min_y }, { region.x, region.y2 }, },
+ { { dx + min_x, dy + max_y }, { region.x, region.y }, },
+ { { dx + max_x, dy + min_y }, { region.x2, region.y2 }, },
- { { dx + max_x, dy + max_y }, { 1, 0 }, },
- { { dx + min_x, dy + max_y }, { 0, 0 }, },
- { { dx + max_x, dy + min_y }, { 1, 1 }, },
+ { { dx + max_x, dy + max_y }, { region.x2, region.y }, },
+ { { dx + min_x, dy + max_y }, { region.x, region.y }, },
+ { { dx + max_x, dy + min_y }, { region.x2, region.y2 }, },
};
ops_draw (builder, offscreen_vertex_data);
else
{
const GskQuadVertex onscreen_vertex_data[GL_N_VERTICES] = {
- { { dx + min_x, dy + min_y }, { 0, 0 }, },
- { { dx + min_x, dy + max_y }, { 0, 1 }, },
- { { dx + max_x, dy + min_y }, { 1, 0 }, },
+ { { dx + min_x, dy + min_y }, { region.x, region.y }, },
+ { { dx + min_x, dy + max_y }, { region.x, region.y2 }, },
+ { { dx + max_x, dy + min_y }, { region.x2, region.y }, },
- { { dx + max_x, dy + max_y }, { 1, 1 }, },
- { { dx + min_x, dy + max_y }, { 0, 1 }, },
- { { dx + max_x, dy + min_y }, { 1, 0 }, },
+ { { dx + max_x, dy + max_y }, { region.x2, region.y2 }, },
+ { { dx + min_x, dy + max_y }, { region.x, region.y2 }, },
+ { { dx + max_x, dy + min_y }, { region.x2, region.y }, },
};
ops_draw (builder, onscreen_vertex_data);
GskRenderNode *start_node = gsk_cross_fade_node_get_start_child (node);
GskRenderNode *end_node = gsk_cross_fade_node_get_end_child (node);
float progress = gsk_cross_fade_node_get_progress (node);
- int start_texture_id;
- int end_texture_id;
+ TextureRegion start_region;
+ TextureRegion end_region;
gboolean is_offscreen1, is_offscreen2;
RenderOp op;
const GskQuadVertex vertex_data[GL_N_VERTICES] = {
add_offscreen_ops (self, builder,
&node->bounds,
start_node,
- &start_texture_id, &is_offscreen1,
+ &start_region, &is_offscreen1,
FORCE_OFFSCREEN | RESET_CLIP | RESET_OPACITY);
add_offscreen_ops (self, builder,
&node->bounds,
end_node,
- &end_texture_id, &is_offscreen2,
+ &end_region, &is_offscreen2,
FORCE_OFFSCREEN | RESET_CLIP | RESET_OPACITY);
ops_set_program (builder, &self->cross_fade_program);
op.op = OP_CHANGE_CROSS_FADE;
op.cross_fade.progress = progress;
- op.cross_fade.source2 = end_texture_id;
+ op.cross_fade.source2 = end_region.texture_id;
ops_add (builder, &op);
- ops_set_texture (builder, start_texture_id);
+ ops_set_texture (builder, start_region.texture_id);
ops_draw (builder, vertex_data);
}
const float min_y = builder->dy + node->bounds.origin.y;
const float max_x = min_x + node->bounds.size.width;
const float max_y = min_y + node->bounds.size.height;
- int top_texture_id;
- int bottom_texture_id;
+ TextureRegion top_region;
+ TextureRegion bottom_region;
gboolean is_offscreen1, is_offscreen2;
RenderOp op;
const GskQuadVertex vertex_data[GL_N_VERTICES] = {
add_offscreen_ops (self, builder,
&node->bounds,
bottom_child,
- &bottom_texture_id, &is_offscreen1,
+ &bottom_region, &is_offscreen1,
FORCE_OFFSCREEN | RESET_CLIP);
add_offscreen_ops (self, builder,
&node->bounds,
top_child,
- &top_texture_id, &is_offscreen2,
+ &top_region, &is_offscreen2,
FORCE_OFFSCREEN | RESET_CLIP);
ops_set_program (builder, &self->blend_program);
- ops_set_texture (builder, bottom_texture_id);
+ ops_set_texture (builder, bottom_region.texture_id);
op.op = OP_CHANGE_BLEND;
- op.blend.source2 = top_texture_id;
+ op.blend.source2 = top_region.texture_id;
op.blend.mode = gsk_blend_node_get_blend_mode (node);
ops_add (builder, &op);
ops_draw (builder, vertex_data);
RenderOpBuilder *builder,
const graphene_rect_t *bounds,
GskRenderNode *child_node,
- int *texture_id_out,
+ TextureRegion *texture_region_out,
gboolean *is_offscreen,
guint flags)
{
(flags & FORCE_OFFSCREEN) == 0)
{
GdkTexture *texture = gsk_texture_node_get_texture (child_node);
- int gl_min_filter = GL_NEAREST, gl_mag_filter = GL_NEAREST;
-
- get_gl_scaling_filters (child_node, &gl_min_filter, &gl_mag_filter);
- *texture_id_out = gsk_gl_driver_get_texture_for_texture (self->gl_driver,
- texture,
- gl_min_filter,
- gl_mag_filter);
+ upload_texture (self, texture, texture_region_out);
*is_offscreen = FALSE;
return;
}
if (cached_id != 0)
{
- *texture_id_out = cached_id;
+ init_full_texture_region (texture_region_out, cached_id);
/* We didn't render it offscreen, but hand out an offscreen texture id */
*is_offscreen = TRUE;
return;
ops_set_render_target (builder, prev_render_target);
*is_offscreen = TRUE;
- *texture_id_out = texture_id;
+ init_full_texture_region (texture_region_out, texture_id);
gsk_gl_driver_set_texture_for_pointer (self->gl_driver, child_node, texture_id);
}